package cn.sql_session.utils;

import cn.sql_session.DataSourceBuild;
import com.mysql.cj.jdbc.Driver;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;


/**
 * &#064;Time 2024 一月 星期三 22:37
 *
 * @author ShangGuan
 */
public class SqlSessionUtils {


    public static <T> T getSqlMapper(Class<T> clazz, String username, String password, String url) {
        try {
            DataSourceBuild dataSourceBuild = DataSourceBuild.dataSourceBuild(url, username, password, new Driver());
            DataSource dataSource = dataSourceBuild.getDataSource();
            return getSqlMapper(dataSource, clazz);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T getSqlMapper(Class<T> clazz, DataSourceBuild dataSourceBuild) {
        DataSource dataSource = dataSourceBuild.getDataSource();
        return getSqlMapper(dataSource, clazz);
    }

    /**
     * 获取sql会话
     *
     * @param druidDataSource 德鲁伊数据源
     * @param clazz           拍手
     * @return {@link T}
     */

    private static <T> T getSqlMapper(DataSource druidDataSource, Class<T> clazz) {
        SqlSession sqlSession = getSqlSession(druidDataSource, clazz);
        return sqlSession.getMapper(clazz);
    }

    private static <T> SqlSession getSqlSession(DataSource dataSource, Class<T> clazz) {
        Environment environment = new Environment("development", new JdbcTransactionFactory(), dataSource);
        Configuration configuration = new Configuration();
        configuration.addMapper(clazz);
        configuration.setEnvironment(environment);
        return getSqlSession(configuration);
    }

    /**
     * 获取 SQL 会话
     *
     * @param dataSource  数据源
     * @param clazz       需要的Mapper的class文件
     * @param packageName 软件包名称  xx/xx/xx/ 表示扫描三级路径下的所有xml文件
     * @return {@link SqlSession }
     * @throws IOException io异常
     **/
    private static <T> SqlSession getSqlSession(DataSource dataSource, Class<T> clazz, String packageName) throws IOException {
        Environment environment = new Environment("development", new JdbcTransactionFactory(), dataSource);
        Configuration configuration = new Configuration();
        configuration.addMapper(clazz);
        configuration.setEnvironment(environment);
        loadXmlMapper(configuration, packageName);
        return getSqlSession(configuration);
    }


    private static SqlSession getSqlSession(Configuration configuration) {
        return SqlSessionFactoryUtils.getSqlSessionFactory(configuration).openSession();
    }


    /**
     * 加载 XML 映射器
     *
     * @param configuration 配置
     * @param packageName   软件包名称 必须是 xx/xx/xx/ 表示扫描三级路径下的所有xml文件
     * @throws IOException io异常
     **/
    private static void loadXmlMapper(Configuration configuration, String packageName) throws IOException {
        // XML 文件的路径，请根据实际情况替换
        List<String> xmlMapperFiles = ScanFileUtils.scanXmlFiles(packageName);
        for (String xmlMapperFile : xmlMapperFiles) {
            InputStream inputStream = SqlSessionUtils.class.getClassLoader().getResourceAsStream(xmlMapperFile);
            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(inputStream, configuration, xmlMapperFile, configuration.getSqlFragments());
            xmlMapperBuilder.parse();
        }
    }

}
